﻿using System;
using System.Collections.Generic;
namespace GxFramework
{
    public class CharTree
    {
        public sealed class CharNode
        {
            static readonly Type Type_Node = typeof(CharNode);

            public Dictionary<char, CharNode> _children;
            public int childCount { get { return null == _children ? 0 : _children.Count; } }
            public char value { get; private set; }
            public string keyword { get; private set; }
            public bool isDirty { get { return !string.IsNullOrEmpty(keyword); } }

            internal CharNode() { }
            protected void AddChild(string text, int index)
            {
                var key = text[index];

                CharNode node = null;

                if (null == _children)
                    _children = DictionaryPool<char,CharNode>.Get();

                if (!_children.TryGetValue(key, out node))
                {
                    node = PoolManager.Get(Type_Node) as CharNode;
                    if (null == node)
                        node = new CharNode();
                    node.value = key;
                    _children[key] = node;
                }

                if (index == text.Length - 1)
                    node.keyword = text;
                else
                    node.AddChild(text, index + 1);
            }
            public CharNode GetChild(char c)
            {
                if (null == _children)
                    return null;
                CharNode node;
                _children.TryGetValue(c, out node);
                return node;
            }
            public void AddKeyword(string text)
            {
                if (string.IsNullOrEmpty(text))
                    return;
                this.AddChild(text, 0);
            }
            public void Clear()
            {
                value = (char)0;
                keyword = null;
                if (null != _children)
                {
                    foreach (var node in _children)
                        node.Value.Clear();
                    DictionaryPool<char, CharNode>.Release(_children);
                    _children = null;
                }
                PoolManager.Release(this);
            }
            //找到最长的匹配
            internal void FindMatchChild(string text, int index, ref CharNode ret)
            {
                if (index >= text.Length)
                    return;
                CharNode node = GetChild(text[index]);
                if (null == node)
                    return;
                if (node.isDirty)
                    ret = node;
                node.FindMatchChild(text, index + 1, ref ret);
            }
        }

        public CharNode _root;
        public CharTree()
        {
            _root = new CharNode();
        }
        public int FindNextMatchIndex(string text, int startIndex, out CharNode ret)
        {
            ret = null;
            int len = text.Length;

            CharNode node;
            for (int i = startIndex; i < len; ++i)
            {
                node = null;
                _root.FindMatchChild(text, i, ref node);
                if (null != node)
                {
                    ret = node;
                    return i;
                }
            }
            return -1;
        }
    }

}